/**
 * Copyright 2010 Mark Wyszomierski
 */
package com.nullpointer.xchatfinal.utils;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.os.Build;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.OutputStream;

/**
 * @author Mark Wyszomierski (markww@gmail.com)
 * @date July 24, 2010
 */
public class ImageUtils {

	private ImageUtils() {
	}

	public static void resampleImageAndSaveToNewLocation(String pathInput,
			String pathOutput) throws Exception {
		Bitmap bmp = resampleImageExactlySize(pathInput, 640);

		OutputStream out = new FileOutputStream(pathOutput);
		bmp.compress(Bitmap.CompressFormat.JPEG, 100, out);
	}

	public static Bitmap resampleImage(String path, int maxDim)
			throws Exception {

		File file = new File(path);

		BitmapFactory.Options o = new BitmapFactory.Options();
		o.inJustDecodeBounds = true;
		BitmapFactory.decodeStream(new FileInputStream(file), null, o);

		// The new size we want to scale to
		int scale = getClosestResampleSize(o.outWidth, o.outHeight, maxDim);

		// Decode with inSampleSize
		BitmapFactory.Options o2 = new BitmapFactory.Options();
		o2.inSampleSize = scale;
		Bitmap bitmap = BitmapFactory.decodeStream(new FileInputStream(file),
				null, o2);
		KiraGameLog.d("image bitmap output " + bitmap.getByteCount() + "size "
				+ bitmap.getWidth() + "/" + bitmap.getHeight() + " scale " + scale);
		return bitmap;
	}

	public static Bitmap resampleImageExactlySize(String path, int maxDim)
			throws Exception {

		BitmapFactory.Options bfo = new BitmapFactory.Options();
		bfo.inJustDecodeBounds = true;
		BitmapFactory.decodeFile(path, bfo);

		BitmapFactory.Options optsDownSample = new BitmapFactory.Options();
		optsDownSample.inSampleSize = getClosestResampleSize(bfo.outWidth,
				bfo.outHeight, maxDim);

		Bitmap bmpt = BitmapFactory.decodeFile(path, optsDownSample);

		Matrix m = new Matrix();

		if (bmpt.getWidth() > maxDim || bmpt.getHeight() > maxDim) {
			BitmapFactory.Options optsScale = getResampling(bmpt.getWidth(),
					bmpt.getHeight(), maxDim);
			m.postScale((float) optsScale.outWidth / (float) bmpt.getWidth(),
					(float) optsScale.outHeight / (float) bmpt.getHeight());
		}

		int sdk = Integer.parseInt(Build.VERSION.SDK);
		if (sdk > 4) {
			int rotation = ExifUtils.getExifRotation(path);
			if (rotation != 0) {
				m.postRotate(rotation);
			}
		}
		return Bitmap.createBitmap(bmpt, 0, 0, bmpt.getWidth(),
				bmpt.getHeight(), m, true);
	}

	public static Bitmap resampleImageForHeight(String path, int maxHeight)
			throws Exception {

		BitmapFactory.Options bfo = new BitmapFactory.Options();
		bfo.inJustDecodeBounds = true;
		BitmapFactory.decodeFile(path, bfo);

		BitmapFactory.Options optsDownSample = new BitmapFactory.Options();
		optsDownSample.inSampleSize = getClosestResampleSize(bfo.outWidth,
				bfo.outHeight, maxHeight);

		Bitmap bmpt = BitmapFactory.decodeFile(path, optsDownSample);

		Matrix m = new Matrix();

		if (bmpt.getHeight() > maxHeight) {
			BitmapFactory.Options optsScale = getResampling(bmpt.getWidth(),
					bmpt.getHeight(), maxHeight);
			m.postScale((float) optsScale.outWidth / (float) bmpt.getWidth(),
					(float) optsScale.outHeight / (float) bmpt.getHeight());
		}

		int sdk = Integer.parseInt(Build.VERSION.SDK);
		if (sdk > 4) {
			int rotation = ExifUtils.getExifRotation(path);
			if (rotation != 0) {
				m.postRotate(rotation);
			}
		}
		return Bitmap.createBitmap(bmpt, 0, 0, bmpt.getWidth(),
				bmpt.getHeight(), m, true);
	}

	private static BitmapFactory.Options getResampling(int cx, int cy, int max) {
		float scaleVal = 1.0f;
		BitmapFactory.Options bfo = new BitmapFactory.Options();
		if (cx > cy) {
			scaleVal = (float) max / (float) cx;
		} else if (cy > cx) {
			scaleVal = (float) max / (float) cy;
		} else {
			scaleVal = (float) max / (float) cx;
		}
		bfo.outWidth = (int) (cx * scaleVal + 0.5f);
		bfo.outHeight = (int) (cy * scaleVal + 0.5f);
		return bfo;
	}

	private static int getClosestResampleSize(int cx, int cy, int maxDim) {
		int max = Math.max(cx, cy);

		int resample = 1;
		for (resample = 1; resample < Integer.MAX_VALUE; resample++) {
			if (resample * maxDim > max) {
				resample--;
				break;
			}
		}

		if (resample > 0) {
			return resample;
		}
		return 1;
	}

	public static BitmapFactory.Options getBitmapDims(String path)
			throws Exception {
		BitmapFactory.Options bfo = new BitmapFactory.Options();
		bfo.inJustDecodeBounds = true;
		BitmapFactory.decodeFile(path, bfo);
		return bfo;
	}
}